package org.uninova.mobis.utils;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

/**
 * SysUtilsImpl
 * @author PAF
 */
public class SysUtilsImpl {
	
	private final SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss yyyy-MM-dd") ;
	
	public SysUtilsImpl() {}
	
	/**
	 * Executes the command passed as input parameter as a command prompt process
	 * @param command		The command to execute
	 * @param fileResult	<code>true</code> if the process generates files as result, <code>false</code> otherwise
	 * @param shortest		<code>true</code> if finding shortest route, <code>false</code> if finding quickest route
	 * @return				the execution result {@link java.lang.String} object
	 */
	public String executeInShell(String[] command, boolean fileResult, boolean shortest) {
		
		Process p = null ;
		try {
			String result = "", strLine ;
			
			// START PROCESS
			ProcessBuilder pb = new ProcessBuilder(command) ;
			pb.redirectErrorStream(true) ;
			
			p = pb.start() ;
			int exitValue = p.waitFor() ;
			
			// GET PROCESS' ERROR STREAM (IF ANY)
			InputStream error = p.getErrorStream();
	         for (int i = 0; i < error.available(); i++) {
	            System.out.println("ERROR: " + error.read());
	         }
			
			File file ;
			// IF PROCESS EXITS OK
			if (exitValue == 0) {
				// IF PROCESS HAS A FILE AS ITS RESULT
				if (fileResult) {
					// IF ROUTE TYPE = SHORTEST
					if (shortest)
						file = new File("shortest-track.gpx") ;
					// IF ROUTE TYPE = QUICKEST
					else
						file = new File("quickest-track.gpx") ;
					// READ FROM FILE
					FileInputStream fstream = new FileInputStream(file) ;
					DataInputStream in = new DataInputStream(fstream) ;
					BufferedReader br = new BufferedReader(new InputStreamReader(in)) ;
					
					while ((strLine = br.readLine()) != null) {
						result += strLine ;
					}
					
					fstream.close() ;
					in.close() ;
					br.close() ;
					file.delete() ;
					
					return result ;
				}
				// IF PROCESS HAS A STRING AS RESULT
				else {
					// READ FROM STRING
					BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())) ;
					
					while ((strLine = stdInput.readLine()) != null) {
							result += strLine ;
					}
					
					stdInput.close() ;
					
					return result ;
				}
			}
		} catch (IOException e) {
			p.destroy() ;
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null ;
	}

	/**
	 * Loads a XML {@link java.lang.String} object into a {@link org.w3c.dom.Document} object.
	 * 
	 * @param xml			the XML {@link java.lang.String} object
	 * @return				the {@link org.w3c.dom.Document} object with the loaded XML code.
	 * @throws Exception
	 */
	public Document loadXMLFromString(String xml) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true) ;
        DocumentBuilder builder = factory.newDocumentBuilder();
       
        InputSource is = new InputSource();
        is.setCharacterStream(new StringReader(xml)) ;
        
        return builder.parse(is);
    }
	
	/**
	 * Converts a {@link java.sql.Timestamp} object into a {@link java.lang.String} object in the format 'HH:mm:ss YYYY-MM-dd'
	 * @param timestamp	The {@link java.sql.Timestamp} object to convert
	 * @return			A {@link java.lang.String} object in the format 'HH:mm:ss YYYY-MM-dd'
	 */		
	public String convertTimestampToString(Timestamp timestamp, String format) {
		if (timestamp == null) {
		      return null;
		} 
		else {
			if (format != null) {
				SimpleDateFormat fmt1 = new SimpleDateFormat(format) ;
				return fmt1.format((java.util.Date) timestamp) ;
			}
			else {
				return fmt.format((java.util.Date) timestamp) ;
			}
		}
	}
	
	/**
	 * Checks if the input {@link java.lang.String} object corresponds to a numeric value
	 * @param str	The input {@link java.lang.String} object
	 * @return		<code>true</code> if the {@link java.lang.String} object is a numeric value; <code>false</code> otherwise
	 */
	public boolean isNumeric(String str) {  
		  try {  
			
			@SuppressWarnings("unused")
			Double d = Double.parseDouble(str);  
			  
		  } catch(NumberFormatException nfe) {  
			  return false;  
		  }  
		  return true;  
	}
}
